package com.lazi.june.gateway.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.HashSet;
import java.util.Set;

/**
 * 网关配置属性类
 * <p>
 * 该类用于管理 June Gateway 的所有配置项，通过 Spring Boot 的 @ConfigurationProperties 注解
 * 自动绑定 application.yml 中以 "june.gateway" 为前缀的配置。
 * <p>
 * 配置示例：
 * <pre>
 * june:
 *   gateway:
 *     jwt:
 *       public-key: ${JWT_PUBLIC_KEY}
 *       algorithms:
 *         - RS256
 *     auth:
 *       whitelist:
 *         - /actuator/**
 *         - /public/**
 *       internal-paths:
 *         - /internal/**
 *       internal-secret: ${INTERNAL_SECRET}
 *     logging:
 *       enabled: true
 *     request-body-cache:
 *       enabled: true
 *     cors:
 *       enabled: true
 *       allowed-origins:
 *         - https://example.com
 *     rate-limit:
 *       enabled: true
 *       per-second: 50.0
 *     blacklist:
 *       enabled: true
 *       window-seconds: 60
 *       threshold: 100
 * </pre>
 *
 * @author huliqian
 * @since 2025/8/21
 */
@Data
@ConfigurationProperties(prefix = "june.gateway")
public class GatewayProperties {

    /**
     * JWT 认证配置
     */
    private JwtConfig jwt = new JwtConfig();

    /**
     * 认证和授权配置
     */
    private AuthConfig auth = new AuthConfig();

    /**
     * 日志配置
     */
    private LoggingConfig logging = new LoggingConfig();

    /**
     * 请求体缓存配置
     */
    private RequestBodyCacheConfig requestBodyCache = new RequestBodyCacheConfig();

    /**
     * CORS 跨域配置
     */
    private CorsConfig cors = new CorsConfig();

    /**
     * 限流配置
     */
    private RateLimitConfig rateLimit = new RateLimitConfig();

    /**
     * 黑名单配置
     */
    private BlacklistConfig blacklist = new BlacklistConfig();

    // ==================== 嵌套配置类 ====================

    /**
     * JWT 认证配置
     */
    @Data
    public static class JwtConfig {
        /**
         * JWT 公钥或密钥
         * <p>
         * 根据 JWT 签名算法的不同，此字段的格式也不同：
         * - HMAC 算法 (HS256/HS512)：配置为共享密钥字符串
         * - RSA 算法 (RS256/RS512)：配置为 JWK (JSON Web Key) 格式的公钥
         * <p>
         * 建议通过环境变量注入：public-key: ${JWT_PUBLIC_KEY}
         */
        private String publicKey;

        /**
         * JWT 支持的签名算法集合
         * <p>
         * 可选值包括：RS256, RS512, HS256, HS512 等
         * 如果为空，系统会根据 JWT Token 的 Header 自动检测算法
         */
        private Set<String> algorithms = new HashSet<>();
    }

    /**
     * 认证和授权配置
     */
    @Data
    public static class AuthConfig {
        /**
         * 白名单路径集合（支持 Ant 风格匹配）
         * <p>
         * 在白名单中的路径将绕过 JWT 认证，直接放行
         */
        private Set<String> whitelist = new HashSet<>();

        /**
         * 内部服务调用密钥
         * <p>
         * 用于服务间内部调用的身份验证
         * <p>
         * 建议通过环境变量注入：internal-secret: ${INTERNAL_SECRET}
         */
        private String internalSecret;

        /**
         * 内部保护路径集合（支持 Ant 风格匹配）
         * <p>
         * 匹配这些路径的请求需要验证 X-Internal-Secret 请求头
         */
        private Set<String> internalPaths = new HashSet<>();
    }

    /**
     * 日志配置
     */
    @Data
    public static class LoggingConfig {
        /**
         * 是否启用请求日志记录
         * <p>
         * 默认值：true
         */
        private boolean enabled = true;
    }

    /**
     * 请求体缓存配置
     */
    @Data
    public static class RequestBodyCacheConfig {
        /**
         * 是否启用请求体缓存
         * <p>
         * 默认值：true
         */
        private boolean enabled = true;
    }

    /**
     * CORS 跨域配置
     */
    @Data
    public static class CorsConfig {
        /**
         * 是否启用 CORS 跨域支持
         * <p>
         * 默认值：true
         */
        private boolean enabled = true;

        /**
         * 允许跨域的源（Origin）
         * <p>
         * 支持通配符 * 表示允许所有源
         * <p>
         * 默认值：["*"]（允许所有源）
         */
        private Set<String> allowedOrigins = new HashSet<>(Set.of("*"));

        /**
         * 允许的 HTTP 方法
         * <p>
         * 默认值：GET, POST, PUT, DELETE, OPTIONS, PATCH
         */
        private Set<String> allowedMethods = new HashSet<>(Set.of("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));

        /**
         * 允许的请求头
         * <p>
         * 默认值：["*"]（允许所有请求头）
         */
        private Set<String> allowedHeaders = new HashSet<>(Set.of("*"));

        /**
         * 是否允许携带凭证（Cookie）
         * <p>
         * 注意：当设置为 true 时，allowedOrigins 不能为 "*"
         * <p>
         * 默认值：true
         */
        private boolean allowCredentials = true;

        /**
         * 预检请求的缓存时间（秒）
         * <p>
         * 默认值：3600（1小时）
         */
        private long maxAge = 3600;
    }

    /**
     * 限流配置
     */
    @Data
    public static class RateLimitConfig {
        /**
         * 是否启用限流功能
         * <p>
         * 默认值：true
         */
        private boolean enabled = true;

        /**
         * 全局限流速率（每秒允许的请求数）
         * <p>
         * 基于 Redisson 的令牌桶算法实现限流
         * <p>
         * 默认值：50.0（每秒 50 个请求）
         */
        private double perSecond = 50.0;

        /**
         * 令牌桶容量（最大突发请求数）
         * <p>
         * 如果不设置，默认等于 perSecond
         */
        private Double capacity;
    }

    /**
     * 黑名单配置
     */
    @Data
    public static class BlacklistConfig {
        /**
         * 是否启用黑名单功能
         * <p>
         * 默认值：true
         */
        private boolean enabled = true;

        /**
         * 黑名单检测时间窗口（秒）
         * <p>
         * 在此时间窗口内统计访问次数
         * <p>
         * 默认值：60（1分钟）
         */
        private long windowSeconds = 60;

        /**
         * 黑名单触发阈值（访问次数）
         * <p>
         * 在时间窗口内超过此次数将被加入黑名单
         * <p>
         * 默认值：100（1分钟内超过100次）
         */
        private int threshold = 100;

        /**
         * 黑名单封禁时长（秒）
         * <p>
         * 默认值：1800（30分钟）
         */
        private long banSeconds = 1800;

        /**
         * 黑名单白名单IP
         * <p>
         * 这些IP永远不会被加入黑名单
         */
        private Set<String> whitelistIps = new HashSet<>();
    }
}